import NextAuth from "next-auth";
import prisma from "@/lib/prisma";
import { PrismaAdapter } from "@auth/prisma-adapter";
import GitHub from "next-auth/providers/github";
import Credentials from "next-auth/providers/credentials";
import { getUserByEmail } from "@/data/user";
import { LoginSchema } from "@/schemas/auth";
import bcrypt from "bcryptjs";
import { isUrl } from "./utils";
import { FileType } from "./enums";
import { getTranslations } from "next-intl/server";

export const { handlers, signIn, signOut, auth } = NextAuth({
  pages: {
    signIn: "/auth/login",
    error: "/auth/error",
  },
  providers: [
    GitHub({
      clientId: process.env.GITHUB_CLIENT_ID,
      clientSecret: process.env.GITHUB_CLIENT_SECRET,
    }),
    Credentials({
      // You can specify which fields should be submitted, by adding keys to the `credentials` object.
      // e.g. domain, username, password, 2FA token, etc.
      credentials: {
        email: {},
        password: {},
      },
      authorize: async (credentials) => {
        const tZod = await getTranslations("zod");
        const validatedFields = LoginSchema(tZod).safeParse(credentials);
        if (validatedFields.success) {
          const { email, password } = validatedFields.data;
          const user = await getUserByEmail(email);
          if (!user || !user.password) return null;

          const passwordMatch = await bcrypt.compare(password, user.password);
          if (passwordMatch) return user;
        }

        return null;
      },
    }),
  ],
  adapter: PrismaAdapter(prisma),
  events: {
    async linkAccount({ user }) {
      await prisma.user.update({
        where: { id: user.id },
        data: {
          emailVerified: new Date(),
        },
      });
    },
    async createUser({ user }) {
      if (user.email) {
        let id = "";
        if (user.image && isUrl(user.image)) {
          const f = await prisma.file.create({
            data: {
              type: FileType.Other,
              data: user.image,
            },
          });
          id = f.id;
          await prisma.user.update({
            where: { id: user.id },
            data: {
              image: id,
            },
          });
        }
      }
    },
  },
  callbacks: {
    async signIn({ user, account }) {
      if (account?.provider !== "credentials") {
        return true;
      }
      if (!user || !user.id) return false;
      if (!user?.emailVerified) return false;
      return true;
    },
    jwt({ token, user, trigger, session }) {
      if (trigger === "update") {
        if (session?.name) token.name = session.name;
        if (session?.image) token.image = session.image;
      }
      if (!user) return token;
      return token;
    },
    session({ session, token }) {
      if (token.sub && session.user) {
        session.user.id = token.sub;
      }
      if (token.name && session.user) {
        session.user.name = token.name as string;
      }
      if (token.image && session.user) {
        session.user.image = token.image as string;
      }
      session.user.role = token.role;
      return session;
    },
  },
  session: {
    strategy: "jwt",
    maxAge: 30 * 24 * 60 * 60, // 30 days
  },
  // TODO: 安全配置
  trustHost: true, // 测试环境信任所有主机
  useSecureCookies: false, // 测试环境允许HTTP
});
